<script lang="ts">
	import type { NodeInfo as RoadmapNodeInfo } from '$lib/api/proto/roadmap_data_api';
	import { Handle, NodeResizer, Position, type NodeProps, type ResizeParams } from '@xyflow/svelte';
	import type { Snippet } from 'svelte';
	import { roadmapStore } from '../../store.svelte';
	import { Trash2 } from 'lucide-svelte';
	import { appStore } from '$lib/stores/app.svelte';
	import { callApi } from '$lib/utils/call_utils';
	import { userStore } from '$lib/stores/user.svelte';
	import { Any } from '$lib/api/proto/google/protobuf/any';
	import { LEARN_LEVEL, LearnState } from '$lib/api/proto/roadmap_data_type_api';

	interface NodeWrapProps {
		nodeProps: NodeProps;
		nodeIcon: Snippet<[]>;
		nodeName: string;
		editIcon?: Snippet<[]>;
		bottomBar?: Snippet<[]>;
		children: Snippet<[]>;
		onSizeChange?: () => void;
	}

	const props: NodeWrapProps = $props();

	const nodeInfo = $derived(props.nodeProps.data as unknown as RoadmapNodeInfo);

	const stateCount = $derived(
		roadmapStore.nodeStateList.filter((item) => item.nodeId == props.nodeProps.id).length
	);

	const lastLearnLevel = $derived(() => {
		const tmpList = roadmapStore.nodeStateList.filter((item) => item.nodeId == props.nodeProps.id);
		for (const state of tmpList) {
			if (state.state?.typeUrl.endsWith('.LearnState')) {
				const level = Any.unpack(state.state, LearnState).learnLevel;
				if (level == LEARN_LEVEL.LEARN_LEVEL_KNOW) {
					return '了解';
				} else if (level == LEARN_LEVEL.LEARN_LEVEL_KNOW_WELL) {
					return '熟悉';
				} else if (level == LEARN_LEVEL.LEARN_LEVEL_MASTER) {
					return '掌握';
				} else if (level == LEARN_LEVEL.LEARN_LEVEL_SKILLFUL) {
					return '精通';
				}
				return '';
			}
		}
		return null;
	});

	let hover = $state(false);

	async function changeSize(params: ResizeParams) {
		if (userStore.userSession == null) {
			return;
		}
		await callApi(
			appStore.roadmapDataApiClient.updateNodeSize({
				sessionId: userStore.userSession,
				roadmapId: roadmapStore.roadmapId,
				nodeId: nodeInfo.nodeId,
				w: params.width,
				h: params.height
			}).response
		);
		await callApi(
			appStore.roadmapDataApiClient.updateNodePosition({
				sessionId: userStore.userSession,
				roadmapId: roadmapStore.roadmapId,
				nodeId: nodeInfo.nodeId,
				x: params.x,
				y: params.y
			}).response
		);
		roadmapStore.onUpdateNode(nodeInfo.nodeId);
	}

	async function removeNode() {
		await roadmapStore.onRemoveNode(nodeInfo.nodeId);
		appStore.addToastMessage({
			level: 'success',
			content: '删除节点成功',
			keepTime: 2000
		});
	}

	$effect(() => {
		if (props.nodeProps.selected) {
			setTimeout(() => {
				roadmapStore.addSelectNodeId(props.nodeProps.id);
			}, 100);
		} else {
			roadmapStore.removeSelectNodeId(props.nodeProps.id);
		}
	});
</script>

<div
	role="none"
	class="w-full h-full border-[1px] border-accent relative rounded-box"
	onmouseenter={() => (hover = true)}
	onmouseleave={() => {
		setTimeout(() => {
			hover = false;
		}, 200);
	}}
>
	<div
		class="bg-secondary text-secondary-content p-2 h-[40px] items-center flex justify-between rounded-box"
	>
		<div class="flex gap-2">
			{@render props.nodeIcon()}
			{props.nodeName}
		</div>
		<div class="flex gap-2">
			{#if roadmapStore.roadmapMode == 'edit' && props.editIcon != undefined}
				{@render props.editIcon()}
			{/if}
			{#if roadmapStore.roadmapMode == 'edit'}
				<button
					type="button"
					title="删除"
					class="btn btn-ghost btn-sm text-error z-50"
					onclick={() => removeNode()}
				>
					<Trash2 size={14} />
				</button>
			{/if}
		</div>
	</div>

	{#if roadmapStore.roadmapMode != 'edit' && stateCount > 0}
		<div
			class="absolute -bottom-[16px] left-[20px] rounded-box bg-accent text-accent-content z-[100] p-1 pl-2 pr-2"
		>
			学习记录: {stateCount}
		</div>
	{/if}

	{#if roadmapStore.roadmapMode != 'edit' && lastLearnLevel() != null}
		<div
			class="absolute -bottom-[16px] right-[20px] rounded-box bg-success text-success-content z-[100] p-1 pl-2 pr-2"
		>
			掌握程度: {lastLearnLevel()}
		</div>
	{/if}

	{#if roadmapStore.roadmapMode != 'edit' && props.bottomBar != undefined}
		{@render props.bottomBar()}
	{/if}
	<Handle
		id="l"
		type="source"
		position={Position.Left}
		style={`background:var(--color-accent);width:10px;height:10px; ${(hover || roadmapStore.inConnect) && roadmapStore.roadmapMode == 'edit' ? 'opacity:1.0' : 'opacity:0'};`}
		isConnectable
	/>
	<Handle
		id="r"
		type="source"
		position={Position.Right}
		style={`background:var(--color-accent);width:10px;height:10px; ${(hover || roadmapStore.inConnect) && roadmapStore.roadmapMode == 'edit' ? 'opacity:1.0' : 'opacity:0'};`}
		isConnectable
	/>
	<Handle
		id="t"
		type="source"
		position={Position.Top}
		style={`background:var(--color-accent);width:10px;height:10px; ${(hover || roadmapStore.inConnect) && roadmapStore.roadmapMode == 'edit' ? 'opacity:1.0' : 'opacity:0'};`}
		isConnectable
	/>
	<Handle
		id="b"
		type="source"
		position={Position.Bottom}
		style={`background:var(--color-accent);width:10px;height:10px; ${(hover || roadmapStore.inConnect) && roadmapStore.roadmapMode == 'edit' ? 'opacity:1.0' : 'opacity:0'};`}
		isConnectable
	/>

	<NodeResizer
		minWidth={200}
		minHeight={200}
		isVisible={props.nodeProps.selected}
		color="var(--color-accent)"
		lineStyle="border-width: 2px;"
		handleStyle="width:10px; height:10px; border-radius:10px;"
		shouldResize={() => roadmapStore.roadmapMode == 'edit'}
		onResizeEnd={(_e, params) => {
			changeSize(params);
		}}
	/>
	<div class="h-[calc(100%-50px)] overflow-auto nowheel bg-base-100">
		{@render props.children()}
	</div>
</div>
